﻿using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace AllInOne
{
    class MainConsole
    {
        #region Fields
        IList<string> samples = new List<string>();
        String samplePath = @"..\Resources\Samples";
        #endregion

        #region Properties

        public IConsole ConsoleUI { get; set; }
        #endregion

        #region Constructor
        
        public MainConsole(IConsole console)
        {
            this.ConsoleUI = console;
            Console.SetIn(new AppConsoleReader(Console.In));
        }

        public MainConsole(): this(new ConsoleUI())
        {
        }
        #endregion

        public void Start()
        {
            this.ShowSamples();

            while (true)
            {
                this.ConsoleUI.Write("Please enter action:");
                var cmd = this.ConsoleUI.ReadLine().Trim().ToLower();
                if (String.IsNullOrEmpty(cmd)) break;

                switch (cmd)
                {
                    case "reload":
                    case "reset":
                        this.ConsoleUI.Clear();
                        this.ShowSamples();
                        break;
                    case "clear":
                        this.ConsoleUI.Clear(); break;
                    case "help":
                        break;
                    case "exit":
                        return;
                    default:
                        int index;
                        string sample = null;
                        if (int.TryParse(cmd, out index))
                        {
                            if (index <= this.samples.Count) sample = this.samples[index - 1];
                        }
                        else
                        {
                            sample = this.samples.FirstOrDefault(s => s.IndexOf(cmd, StringComparison.InvariantCultureIgnoreCase) >= 0);
                        }

                        if (String.IsNullOrEmpty(sample))
                        {
                            this.ConsoleUI.WriteLine(ConsoleColor.Red, "[{0}] can't be recognized.", cmd);
                        }
                        else
                        {
                            var source = File.ReadAllText(Path.Combine(samplePath, sample));
                            this.ConsoleUI.WriteLine(null);

                            this.ConsoleUI.WriteLine(ConsoleColor.Blue, "Outputs:");
                            var cr = Compiler.CompileAndRun(source);

                            if (cr.Errors.Count > 0)
                            {
                                ShowErrors(cr.Errors);
                            }
                            this.ConsoleUI.WriteLine(null);                          
                        }
                        break;
                }

            }
        }

        private void ShowErrors(CompilerErrorCollection errorCollection)
        {
            this.ConsoleUI.WriteLine(ConsoleColor.Red, "Error occurred:");
            foreach (CompilerError error in errorCollection)
            {
                this.ConsoleUI.WriteLine(error.ErrorText);
            }  
        }

        private void ShowSamples()
        {
            this.ConsoleUI.WriteLine("Code Samples:");

            this.samples = AppConfig.CSharpApp.AppList.Select(a=>a.Location).ToArray();

            for (int i = 0; i < samples.Count; i++)
            {
                var color = i % 2 == 0 ? ConsoleColor.Yellow : ConsoleColor.Green;
                this.ConsoleUI.WriteLine(color, "{0}. {1}", i + 1, samples[i]);
            }

            this.ConsoleUI.WriteLine(null);
        }

    }

    class AppConsoleReader : TextReader
    {
        TextReader reader;
        public AppConsoleReader(TextReader tr)
        {
            this.reader = tr;
        }

        public override string ReadLine()
        {
            return reader.ReadLine();
        }

        public override int Read()
        {
            return 0;
        }

    }
}
